package com.zhongke.cotrun.controller;

import com.github.pagehelper.util.StringUtil;
import com.zhongke.cotrun.common.util.APIResponse;
import com.zhongke.cotrun.common.util.AddIntegralUtils;
import com.zhongke.cotrun.common.util.Encrypt;
import com.zhongke.cotrun.common.util.RedisUtil;
import com.zhongke.cotrun.mapper.UserInfoMapper;
import com.zhongke.cotrun.model.exception.MyException;
import com.zhongke.cotrun.model.pojo.UserInfo;
import com.zhongke.cotrun.model.pojo.UserInforCompany;
import com.zhongke.cotrun.model.resultpackage.CodeMsg;
import com.zhongke.cotrun.model.validator.UserValidator;
import com.zhongke.cotrun.service.MessageService;
import com.zhongke.cotrun.service.UserInfoService;
import com.zhongke.cotrun.shiro.sys.shiro.ShiroUtils;
import com.zhongke.cotrun.shiro.web.entity.WebMenuEntity;
import com.zhongke.cotrun.shiro.web.entity.WebUserEntity;
import com.zhongke.cotrun.shiro.web.realm.UsernamePhoneCodeToken;
import com.zhongke.cotrun.shiro.web.service.WebMenuService;
import io.swagger.annotations.*;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpSession;
import javax.validation.constraints.NotNull;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


@Api(tags = "用户管理相关接口")
@RestController
@RequestMapping("/user")
@Validated
public class UserInfoController {
    @Autowired
    AddIntegralUtils addIntegralUtils;

    @Autowired
    UserInfoService userInfoService;
    @Autowired
    MessageService messageService;
    @Autowired
    private WebMenuService webMenuService;
    @Autowired
    UserInfoMapper userInfoMapper;

    private final Logger logger = LoggerFactory.getLogger(UserInfoController.class);
    private final String ENCRYPT_KEY = "cotrun";

    @Autowired
    private RedisUtil redisUtil;

    @Value("${cotrun.expire}")
    private Integer expire;

    /**
     * 获取本人邀请码
     *
     * @return
     */
    @ApiOperation(value = "获取本人邀请码")
    @GetMapping("/getShareUrl")
    public APIResponse getShareUrl() throws MyException {
        WebUserEntity userInfo = ShiroUtils.getWebUser();
        if (userInfo == null) {
            throw new MyException(CodeMsg.MUST_LOGIN_ERROP);
        }
        Encrypt encrypt = new Encrypt();
        encrypt.setKey(ENCRYPT_KEY);    //调用set函数设置密钥。
        encrypt.setEncString(String.valueOf(userInfo.getUserId()));//将要加密的明文传送给Encrypt.java进行加密计算。

        return APIResponse.returnSuccess(encrypt.getStrMi());
    }

    /**
     * 注册接口
     *
     * @param userInfo
     * @return
     * @throws MyException
     */
    @ApiOperation(value = "用户注册接口", httpMethod = "POST", response = APIResponse.class)
    @PostMapping("/register")
    public APIResponse register(@Validated({UserValidator.InSet.class}) UserInfo userInfo,
                                @ApiIgnore HttpSession session) throws MyException, ParseException {
        if (!"202010".equals(userInfo.getMessage())) {
            if (!messageService.verifyCode(userInfo.getMessage(), session)) {
                return APIResponse.returnFail(CodeMsg.MESSAGE_ERROR);
            }
        }

        //是否邀请注册
        String shareNum = userInfo.getShareNum();
        if (StringUtil.isNotEmpty(shareNum)) {
            Encrypt encrypt = new Encrypt();
            encrypt.setKey(ENCRYPT_KEY);
            encrypt.setDesString(shareNum);
            userInfo.setShareUserId(Integer.parseInt(encrypt.getStrM()));
        }

        if (userInfoService.useRegistration(userInfo)) {
            //积分
            Map m = addIntegralUtils.getMapOfUserEntity(userInfo, 0, "/user/register",
                    "VIP0", "用户注册时候增加:", session);

            //邀请人增加积分
            if (userInfo.getShareUserId() != null && userInfo.getShareUserId() > 0) {
                UserInfo shareUserInfo = userInfoService.selectUserInfoByid(userInfo.getShareUserId());
                if (shareUserInfo != null)
                    m = addIntegralUtils.getMapOfUserEntity(shareUserInfo, 0, "/user/registerShare",
                            "VIP0", "邀请用户注册时候增加:", session);
            }
            return APIResponse.returnSuccess(m);


        }
        return APIResponse.returnFail(CodeMsg.REGISTER_ERROR);

    }


    /**
     * 公司注册
     *
     * @param userInfo
     * @param session
     * @return
     * @throws MyException
     */
    @PostMapping("/companyRegister")
    public APIResponse companyRegister(@Validated({UserValidator.InSet.class})
                                               UserInforCompany userInfo,
                                       @ApiIgnore HttpSession session) throws MyException {

        if (!"202010".equals(userInfo.getMessage())) {
            if (!messageService.verifyCode(userInfo.getMessage(), session)) {
                return APIResponse.returnFail(CodeMsg.MESSAGE_ERROR);

            }

        }


        if (userInfoService.companyUseRegistration(userInfo)) {
            return APIResponse.returnSuccess();

        }
        return APIResponse.returnFail(CodeMsg.REGISTER_ERROR);

    }

    /**
     * 登录接口
     *
     * @param phoneNumber
     * @param passwd
     * @return
     * @throws MyException
     */
    @ApiOperation(value = "用户登录", httpMethod = "POST", response = APIResponse.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phoneNumber", value = "手机号", required = true),
            @ApiImplicitParam(name = "message", value = "验证码", required = false),
            @ApiImplicitParam(name = "passwd", value = "密码", required = false)
    })
    @PostMapping(value = "/login")
    public APIResponse login(
            @NotNull(message = "账号不能为空")
                    String phoneNumber,
            @RequestParam(required = false)
                    String message,
            @RequestParam(required = false)
                    String passwd,
            @ApiIgnore HttpSession session) {
        logger.info(new StringBuilder().append("login phoneNumber:" + phoneNumber).append(" message:" + message).toString());
        String sessionId; //sessionId既前端设置的token
        try {
            AuthenticationToken token;
            if (StringUtils.isNotBlank(message)) {
                token = new UsernamePhoneCodeToken(phoneNumber, message, session);
            } else {
                token = new UsernamePasswordToken(phoneNumber, passwd);
            }
            Subject subject = ShiroUtils.getSubject();
            subject.login(token);
            sessionId = subject.getSession().getId().toString();    //获取sessionId,返回给请求端
            redisUtil.set("cotrun_web_user:"+ShiroUtils.getUserId1().toString(), sessionId, expire);
        } catch (UnknownAccountException e) {
            return APIResponse.returnFail("账号或密码不正确");
        } catch (IncorrectCredentialsException e) {
            return APIResponse.returnFail("账号或密码不正确");
        } catch (LockedAccountException e) {
            return APIResponse.returnFail("账号已被锁定,请联系管理员");
        } catch (AuthenticationException e) {
            return APIResponse.returnFail("账户验证失败");
        }
        List<WebMenuEntity> menuList = webMenuService.queryUrlList(ShiroUtils.getWebUserId());  //菜单列表
        List<WebMenuEntity> permList = webMenuService.queryAllPerms1(ShiroUtils.getWebUserId());    //权限列表
        WebUserEntity userInfo = ShiroUtils.getWebUser();
        userInfo.setPasswd(null);
        userInfo.setPermList(permList);
        userInfo.setMenuList(menuList);
        userInfo.setToken(sessionId);
        return APIResponse.returnSuccess(userInfo);
    }

    /**
     * 修改自己的信息
     *
     * @param userInfo
     * @param session
     * @return
     * @throws MyException userId 用户的id
     *                     phoneNumber //手机号码
     *                     passwd //密码
     */
    @ApiOperation(value = "修改信息", httpMethod = "POST", response = APIResponse.class)
    @PostMapping("/updateUserinfo")
    public APIResponse updateUserinfo(UserInfo userInfo, @ApiIgnore HttpSession session) throws MyException, ParseException {
        UserInfo userInfo1 = userInfoService.selectUserInfoByid(userInfo.getUserId());
        if (userInfoService.updateUserInfo(userInfo, session)) {

            //用户积分生效
            Map m = addIntegralUtils.getMapOfUserEntity(userInfo1, userInfo1.getComplete(), "/user/updateUserinfo",
                    "VIP0", "用户完善信息的时候增加:", session);
//            Map m = getMapOfUserEntity(userInfo1, session, u);
            return APIResponse.returnSuccess(m);
        }
        return APIResponse.returnFail(CodeMsg.UPDATE_ERROR);

    }

    /**
     * 用户身份分解工具类
     *
     * @param userInfo
     * @param session
     * @param u
     * @return
     * @throws ParseException
     */
    private Map getMapOfUserEntity(UserInfo userInfo, @ApiIgnore HttpSession session, Integer u) throws ParseException {
        Map m = null;
        if (u == null || u == 0) {
            String identity = userInfo.getIdentity();
            List<String> l = new ArrayList<>();
            if (identity == null) {
                l.add("普通用户");
            } else {
                String[] s = identity.split(",");
                l = Arrays.asList(s);
            }

            m = addIntegralUtils.addIntegral("/user/updateUserinfo", "VIP0", l, userInfo.getUserId(), "用户完善信息的时候增加:" + session.getAttribute("value"), session);

        }
        return m;
    }

    /**
     * 修改企业用户信息
     *
     * @param userInforCompany
     * @return
     */
    @ApiOperation(value = "修改企业信息", httpMethod = "POST")
    @PostMapping("/updateUserInfoForCompany")
    public APIResponse updateUserInfoForCompany(UserInforCompany userInforCompany) throws MyException {
        if (userInfoService.updateUserInfoForCompany(userInforCompany)) {
//            addIntegralUtils.addIntegral("完善企业信息",userInforCompany.getUserId(),session)
            return APIResponse.returnSuccess();

        }
        return APIResponse.returnFail(CodeMsg.UPDATE_ERROR);
    }

    /**
     * 查看用户信息
     *
     * @return
     */
    @ApiOperation(value = "查看用户信息")
    @GetMapping("/selectUserById")
    public APIResponse selectUserById() throws MyException {
        WebUserEntity userInfo = ShiroUtils.getWebUser();
        if (userInfo == null) {
            throw new MyException(CodeMsg.MUST_LOGIN_ERROP);
        }
        Integer userId = userInfo.getUserId().intValue();
//        String type = userInfo.getType();
//        if ("1".equals(type)) {
//            return APIResponse.returnSuccess(userInfoService.selectUserInfoByid(userId));
//        }
        return APIResponse.returnSuccess(userInfoService.selectUserInfoCompanyById(userId));
    }

    /**
     * 退出
     *
     * @param session
     * @return
     */
    @ApiOperation(value = "退出", httpMethod = "GET")
    @GetMapping("/loginOut")
    public APIResponse loginOut(@ApiIgnore HttpSession session) {
        Long id = ShiroUtils.getUserId1();
        session.invalidate();
        ShiroUtils.logout();
        if(id!=null)
            redisUtil.remove("cotrun_web_user:" + id.toString());
        return APIResponse.returnSuccess();
    }


    /**
     * 校验登录密码
     *
     * @param passwd
     * @param session
     * @return
     */
    @ApiOperation(value = "校验登录密码")
    @PostMapping("/checkingPasswd")
    public APIResponse checkingPasswd(
            @ApiParam(value = "密码", required = true)
            @NotNull(message = "密码不能为空") String passwd,
            @ApiIgnore HttpSession session) throws MyException {

        if (userInfoService.verifyPassword(passwd, session)) {
            return APIResponse.returnSuccess();
        }
        return APIResponse.returnFail(CodeMsg.PASSWORD_ERROR);
    }

    /**
     * 校验手机号
     *
     * @param phoneNumber
     * @param session
     * @return
     * @throws MyException
     */
    @ApiOperation(value = "校验登手机号")
    @GetMapping("/checkingPhoneNumber")
    public APIResponse checkingPhoneNumber(
            @ApiParam(value = "手机号", required = true)
            @NotNull(message = "手机号码不能为空") String phoneNumber,
            @NotNull(message = "验证码不能为空") String message,
            @ApiIgnore HttpSession session) throws MyException {

        if (!messageService.verifyCode(message, session)) {
            throw new MyException(CodeMsg.MESSAGE_ERROR);
        }


        if (userInfoService.verifyPhoneNumber(phoneNumber,
                session)) {
            return APIResponse.returnSuccess();
        }

        return APIResponse.returnFail(CodeMsg.PHONENUMBER_ERROR);
    }

    /**
     * 根据id查询用户过滤掉敏感信息
     *
     * @param linkUserId
     * @return
     */
    @GetMapping("/selectUserInfoByFilter")
    public APIResponse selectUserInfoByFilter(@NotNull(message = "id号不能为空") Integer linkUserId) {
        return APIResponse.returnSuccess(userInfoService.selectUserInfoByIdFilter(linkUserId));
    }

}
